package edu.sjtu.context.prob.remote;

import java.util.ArrayList;
import java.util.List;

import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.sjtu.context.core.ContextChangeEvent;
import edu.sjtu.context.core.LocalContextChangeListener;
import edu.sjtu.context.core.RemoteContextChangeListener;
import edu.sjtu.context.prob.RemoteContextProb;
import edu.sjtu.context.test.TestReceive;

public class DefaultRemoteContextProb implements RemoteContextProb, MessageListener {
	/**
	 * Connection url.
	 */
	private String connUrl;
	/**
	 * Subscribe topic.
	 */
	private String topic;
	/**
	 * the ontology which the detected context will be apply on.
	 */
	private String ontName;
	/**
	 * list of listeners
	 */
	private List<RemoteContextChangeListener> lis;
	/**
	 * log instance
	 */
	private Log log = null;
	/**
	 * Constructor.
	 */
	public DefaultRemoteContextProb(){
		this.lis = new ArrayList<RemoteContextChangeListener>();
		log = LogFactory.getLog(this.getClass());
	}
	
	public void addRemoteContextChangeListener(RemoteContextChangeListener lis) {
		this.lis.add(lis);
	}

	/*public long getFrequency() {
		return this.frequency;
	}*/

	public String getOntName() {
		return this.ontName;
	}

	public int removeRemoteContextChangeListener(RemoteContextChangeListener lis) {
		int index = this.lis.indexOf(lis);
		this.lis.remove(lis);
		return index;
	}

	/*public void setFrequency(long frequency) {
		this.frequency = frequency;
	}*/

	public void setOntName(String ontName) {
		this.ontName = ontName;
	}

	public void run() {
		try{
			ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(this.connUrl);
			Connection connection = factory.createConnection();
	        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
	        Topic topic = session.createTopic(this.topic);
	        
	        MessageConsumer consumer = session.createConsumer(topic);
	        consumer.setMessageListener(new TestReceive());
	        connection.start();
		} catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public void setSubscribeTopic(String topic){
		this.topic = topic;
	}
	
	public void setConnUrl(String connUrl){
		this.connUrl = connUrl;
	}
	
	/**
	 * Callback method from MessageListener. This method will be called when subscribed topic
	 * publish new message.
	 */
	public void onMessage(javax.jms.Message message){
		javax.jms.TextMessage msg;
		ContextChangeEvent event;
		if(message instanceof TextMessage){
			msg = (TextMessage)message;
			event = this.createEvent(msg);
			if(event == null){
				return;
			}
			for(RemoteContextChangeListener li : this.lis){
				li.sendRemoteContext(event);
			}
		}
	}
	
	/**
	 * Create context change event object based on the message received from subscribed topic.
	 * The message format is ClassName/ContextName/=ContextValue
	 * @param message
	 * 		The message received from subscribed topic.
	 * @return
	 * 		ContextChangeEvent if the message is in correct format, or return null.
	 */
	private ContextChangeEvent createEvent(javax.jms.TextMessage message){
		try{			
			String text = message.getText();
			log.info("Receive remote context change: " + text);
			String[] textArr = text.split("=");
			if(textArr.length == 2){
				String[] prefix = textArr[0].split("/");
				if(prefix.length == 2){
					return new ContextChangeEvent(this, prefix[1], textArr[1], this.ontName, prefix[0]);
				}else{
					return null;
				}
			}else{
				return null;
			}
		} catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}
}
